package main

import (
	"fmt"
	"sync"
	"time"
)

// 定义一个需要复用的对象（例如缓冲区）
type Buffer struct {
	data []byte
}

func main() {
	// 1. 创建对象池，指定新对象的创建函数
	var pool sync.Pool
	// 当池为空时自动调用此函数创建新对象
	pool.New = func() interface{} {
		fmt.Println("创建新的 Buffer 对象")
		return &Buffer{
			data: make([]byte, 1024), // 1KB 缓冲区
		}
	}

	// 2. 测试无池情况下的对象创建（对比性能）
	//testWithoutPool()

	// 3. 测试使用对象池的情况
	testWithPool(&pool)
}

// 测试使用对象池复用对象
func testWithPool(pool *sync.Pool) {
	start := time.Now()
	var wg sync.WaitGroup

	// 模拟 1000 个并发任务，从池中获取和归还对象
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			// 从池中获取对象（类型断言）
			buf := pool.Get().(*Buffer) //Get() 和 Put() 方法是并发安全的，可在多 goroutine 中直接使用
			// 模拟使用对象（清空数据，避免残留）
			buf.data = buf.data[:0]

			// 使用完毕后归还到池
			defer pool.Put(buf) //Get() 和 Put() 方法是并发安全的，可在多 goroutine 中直接使用
		}()
	}

	wg.Wait()
	fmt.Printf("使用对象池耗时: %v\n", time.Since(start))
}

/**
// 测试不使用对象池，每次创建新对象
func testWithoutPool() {
	start := time.Now()
	var wg sync.WaitGroup

	// 模拟 1000 个并发任务，每个任务创建一个新对象
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			// 每次创建新对象
			buf := &Buffer{data: make([]byte, 1024)}
			// 模拟使用对象
			_ = buf.data
		}()
	}

	wg.Wait()
	fmt.Printf("不使用对象池耗时: %v\n", time.Since(start))
}
*/
